#include <stdio.h>
#include <string.h>
#include <SDL2/SDL.h>
#include <libavutil/imgutils.h>

//event message
#define REFRESH_EVENT (SDL_USEREVENT + 1)
#define QUIT_EVENT (SDL_USEREVENT + 2)

int thread_exit = 0;

int refresh_video_timer(void *udata)
{

    thread_exit = 0;

    while (!thread_exit)
    {
        SDL_Event event;
        event.type = REFRESH_EVENT;
        SDL_PushEvent(&event);
        SDL_Delay(40);
    }

    thread_exit = 0;

    //push quit event
    SDL_Event event;
    event.type = QUIT_EVENT;
    SDL_PushEvent(&event);

    return 0;
}

int main(int argc, char *argv[])
{

    FILE *video_fd = NULL;

    SDL_Event event;
    SDL_Rect rect;

    Uint32 pixformat = 0;

    SDL_Window *win = NULL;
    SDL_Renderer *renderer = NULL;
    SDL_Texture *texture = NULL;

    SDL_Thread *timer_thread = NULL;

    int w_width = 960, w_height = 540;
    const int video_width = 960, video_height = 540;

    const char *path = "/Users/yuanxuzhen/tools/音视频/out.yuv";

    const unsigned int yuv_frame_len = video_width * video_height * 12 / 8;

    //initialize SDL
    if (SDL_Init(SDL_INIT_VIDEO))
    {
        fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
        return -1;
    }

    //creat window from SDL
    win = SDL_CreateWindow("YUV Player",
                           SDL_WINDOWPOS_UNDEFINED,
                           SDL_WINDOWPOS_UNDEFINED,
                           w_width, w_height,
                           SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
    if (!win)
    {
        fprintf(stderr, "Failed to create window, %s\n", SDL_GetError());
        goto __FAIL;
    }

    renderer = SDL_CreateRenderer(win, -1, 0);

    //IYUV: Y + U + V  (3 planes)
    //YV12: Y + V + U  (3 planes)
    pixformat = SDL_PIXELFORMAT_IYUV;

    //create texture for render
    texture = SDL_CreateTexture(renderer,
                                pixformat,
                                SDL_TEXTUREACCESS_STREAMING,
                                video_width,
                                video_height);

    //创建AVFrame
    int ret = 0;

    if (ret < 0)
    {
        printf("av_frame_get_buffer fail error =  %s", av_err2str(ret));
        goto __FAIL;
    }
    //第九步 创建buffer用于存储文件读取出来的数据
    size_t buffer_size = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, video_width, video_height, 32);

    uint8_t *buffer = malloc(buffer_size);

    //open yuv file
    video_fd = fopen(path, "rb");
    if (!video_fd)
    {
        fprintf(stderr, "Failed to open yuv file\n");
        goto __FAIL;
    }

    //read block data

    timer_thread = SDL_CreateThread(refresh_video_timer,
                                    NULL,
                                    NULL);

    do
    {
        //Wait
        SDL_WaitEvent(&event);
        if (event.type == REFRESH_EVENT)
        {
            //not enought data to render
            int ret = fread(buffer, buffer_size, 1, video_fd);
            if (ret == 0)
            {
                thread_exit = 1;
                break;
            }

            SDL_UpdateTexture(texture, NULL, buffer, video_width);

            //FIX: If window is resize
            rect.x = 0;
            rect.y = 0;
            rect.w = w_width;
            rect.h = w_height;

            SDL_RenderClear(renderer);
            SDL_RenderCopy(renderer, texture, NULL, &rect);
            SDL_RenderPresent(renderer);
        }
        else if (event.type == SDL_WINDOWEVENT)
        {
            //If Resize
            SDL_GetWindowSize(win, &w_width, &w_height);
        }
        else if (event.type == SDL_QUIT)
        {
            thread_exit = 1;
        }
        else if (event.type == QUIT_EVENT)
        {
            break;
        }
    } while (1);

__FAIL:

    //close file
    if (video_fd)
    {
        fclose(video_fd);
    }

    if (buffer)
    {
        free(buffer);
    }

    SDL_Quit();

    return 0;
}
